package com.mxpio.erp.equipment.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.mxpio.erp.common.equipment.entity.*;
import com.mxpio.erp.common.equipment.service.*;
import com.mxpio.erp.equipment.utils.OrderNumberUtil;
import com.mxpioframework.common.exception.MBootException;
import com.mxpioframework.common.vo.Result;
//import com.mxpioframework.dingtalk.enums.DingTalkEnums;
//import com.mxpioframework.dingtalk.pojo.DingTalkMessagePojo;
//import com.mxpioframework.dingtalk.pojo.LinkTypeContent;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.policy.impl.CrudType;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.Operator;
//import com.mxpioframework.message.service.MessageService;
import com.mxpioframework.security.entity.User;
import com.mxpioframework.security.service.DeptService;
import com.mxpioframework.security.service.UserService;
import com.mxpioframework.security.util.SecurityUtils;
import com.mxpioframework.system.service.impl.BaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 设备维修
 * @Author: jeecg-boot
 * @Date: 2021-09-23
 * @Version: V1.0
 */
@Service
@Slf4j
public class EquipmentRepairServiceImpl extends BaseServiceImpl<EquipmentRepair> implements EquipmentRepairService {

    /**
     * 待派工
     */
    public static final Integer APPLY = 10;
    /**
     * 待维修
     */
    public static final Integer SEND = 20;
    /**
     * 维修中
     */
    public static final Integer REPAIR = 30;
    /**
     * 暂停中
     */
    public static final Integer STOP = 35;
    /**
     * 待验收
     */
    public static final Integer FINISH = 40;
    /**
     * 验收完成
     */
    public static final Integer CHECKED = 50;

    /**
     * 取消/终止
     */
    public static final Integer CANCLE = 90;
    public static final String SOURCE_SG = "手工录入";
    public static final String SOURCE_JJ = "紧急报修";

    public static final String[] channelCodes = {"dingtalkWorkMsg"};

    @Autowired
    private EquipmentRepairOperationService repairOperationService;
    @Autowired
    private EquipmentRepairTransferService repairTransferService;

    @Autowired
    private UserService userService;
    @Autowired
    private EquipmentAreaService equipmentAreaService;
    @Autowired
    private EquipmentEqpBasicsService equipmentService;
    @Autowired
    private EquipmentEqpStatusRecordsService equipmentEqpStatusRecordsService;
//    @Resource
//    private ActivitiInstanceController activitiInstanceController;
    @Autowired
    private EquipmentPersonGroupDetailService equipmentPersonGroupDetailService;
    @Autowired
    private DeptService deptService;
    @Autowired
    private EquipmentRepairOperationService equipmentRepairOperationService;

   /* @Resource
    private MessageService messageService;//消息*/

    @Autowired
    private FaultTypeService faultTypeService;


    /*@Value("${dingtalk.executeDetailUrl}")
    private String executeDetailUrl;
    @Value("${dingtalk.applyDetailUrl}")
    private String applyDetailUrl;*/
public Page<EquipmentRepair> getTpmRepairIPage(Criteria criteria, Pageable page, String flag, String applyStart, String applyEnd, String planRepairStart, String planRepairEnd, String failureTime, HttpServletRequest req) {
    User sysUser = SecurityUtils.getLoginUser();
    String username = sysUser.getUsername();
//    Linq linq = JpaUtil.linq(EquipmentRepair.class).where(criteria);
    //申请工单关联工单
    if ("apply".equals(flag)) {
        criteria.addCriterion("applyId",Operator.EQ, username)
                .or().addCriterion("createBy",Operator.EQ, username);
    } else if ("send".equals(flag)) {//派工模式
        criteria.and().addCriterion("dispatchMode",Operator.EQ, "assign")
                .addCriterion("recePersonId",Operator.EQ, username)
                .addCriterion("orderStatus",Operator.EQ, 10);
    } else if ("grab".equals(flag)) { //抢单模式
        criteria.and().addCriterion("dispatchMode",Operator.EQ, "grab")
                .addCriterion("orderStatus",Operator.EQ, 10);
        //获取当前用户的所属部门
        Set<String> deps = deptService.getDeptKeysByUser(sysUser.getUsername(),"id");
        //todo wait groups
        //获取当前用户所属的群组
        List<String> groups = equipmentPersonGroupDetailService.selectByUsername(sysUser.getUsername());
//        List<String> departs = deps.stream().map(a -> a.getId()).collect(Collectors.toList());
        groups.addAll(deps);
        criteria.addCriterion("orgId",Operator.IN, groups);
//                .end();
    } else if ("toRepair".equals(flag)) {
        criteria.and().addCriterion("distributePersonId",Operator.EQ, username)//查询当前用户为执行人
                .addCriterion("orderStatus",Operator.EQ, 20) //查询状态为20
                ;
    } else if ("repairing".equals(flag)) {
        criteria.and().addCriterion("distributePersonId",Operator.EQ,  username)//查询当前用户为执行人
                .addCriterion("orderStatus",Operator.EQ, 30) //查询状态为30
                ;
    } else if ("stop".equals(flag)) {
        criteria.and().addCriterion("distributePersonId",Operator.EQ, username)//查询当前用户为执行人
                .addCriterion("orderStatus",Operator.EQ, 35) //查询状态为35
                ;
    } else if ("repair".equals(flag)) {
       int[] status = {20, 30, 35} ;
        criteria.and().addCriterion("distributePersonId",Operator.EQ, username)//查询当前用户为执行人
                .addCriterion("orderStatus",Operator.IN, status)  //查询状态为20,30,35
                ;
    } else if ("check".equals(flag)) {
        criteria.and().addCriterion("orderStatus",Operator.EQ, 40)  //查询状态为40
                ;
        //查询当前用户为申请人或者部门负责人
        criteria.and().addCriterion("applyId",Operator.EQ, username)
                .or().addCriterion("recePersonId",Operator.EQ,username)
                ;
    } else if ("record".equals(flag)) {

        //查询当前用户为申请人或者部门负责人
        criteria.and().addCriterion("applyId",Operator.EQ,  username)
                .or().addCriterion("recePersonId",Operator.EQ, username)
                .or().addCriterion("createBy",Operator.EQ, username)
                ;
        criteria.and().addCriterion("orderStatus",Operator.EQ,  50)  //查询状态为50
                ;
    } else if ("repairOverdue".equals(flag)) {//逾期未执行
        int[] status = {20, 30, 35} ;
        //查询状态为20,30,35
        criteria.and().addCriterion("distributePersonId",Operator.EQ, username)//查询当前用户为执行人
                .addCriterion("orderStatus",Operator.IN,status)  //查询状态为20,30,35
                .addCriterion("planRepairEndDate",Operator.LT,DateUtil.now())//当前时间大于预计完成时间的未完工工单
                ;
    } else if ("overdueFinish".equals(flag)) {//逾期完成
        int[] status = {40, 50} ;
        //查询状态为40, 50
        criteria.and().addCriterion("orderStatus",Operator.IN, status)  //查询状态为20,30,35
                .addCriterion("planRepairEndDate",Operator.LT,DateUtil.now())//当前时间大于预计完成时间的未完工工单
                .addCriterion("overFlag",Operator.EQ, 1)//当前时间大于预计完成时间的未完工工单
                ;
        //查询当前用户为相关人
        criteria.and().addCriterion("applyId",Operator.EQ, username)
                .or().addCriterion("recePersonId",Operator.EQ,username)
                .or().addCriterion("createBy",Operator.EQ,username)
                .or().addCriterion("distributePersonId",Operator.EQ,username)
                .or().addCriterion("checkUser",Operator.EQ,username)
                ;

    }
    /**  时间查询开始 */
    //查询申请时间大于等于
    if (StringUtils.isNotBlank(applyStart)) {
         criteria.and().addCriterion("applyTime",Operator.GE,applyStart + " 00:00:00")
                ;
    }
    //查询申请时间小于等于
    if (StringUtils.isNotBlank(applyEnd)) {
        criteria.and().addCriterion("applyTime",Operator.LE,applyEnd + " 23:59:59")
                ;
    }
    //查询计划开始时间大于等于
    if (StringUtils.isNotBlank(planRepairStart)) {
        criteria.and().addCriterion("planRepairStartDate",Operator.GE,planRepairStart + " 00:00:00")
                ;
    }
    //查询计划结束时间小于等于
    if (StringUtils.isNotBlank(planRepairEnd)) {
        criteria.and().addCriterion("planRepairEndDate",Operator.LE,planRepairEnd + " 23:59:59")
                ;
    }
    //查询故障时间
    if (StringUtils.isNotBlank(failureTime)) {
        criteria.and().addCriterion("failureDate",Operator.LE,failureTime )
                ;
    }


    /**  时间查询结束 */
//    queryWrapper.orderByDesc("update_time", "create_time");
    return JpaUtil.linq(EquipmentRepair.class).where(criteria).paging(page);
//    return this.listPage(EquipmentRepair.class, page, criteria);
}


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delMain(String id) {
        this.delete(EquipmentRepair.class, id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delBatchMain(Collection<? extends Serializable> idList) {
        Criteria c = Criteria.create().addCriterion("id", Operator.IN, idList);
        this.deleteBatch(EquipmentRepair.class, c);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveRepair(EquipmentRepair equipmentRepair) {
        if (equipmentRepair.getCrudType().name().equals("UPDATE")){
            equipmentRepair.setCrudType(CrudType.SAVE);
        }
        //设置工单编码
        equipmentRepair.setOrderCode(OrderNumberUtil.getCode("WX"));
        //设置状态
        equipmentRepair.setOrderStatus(APPLY);
        User loginUser = SecurityUtils.getLoginUser();
        //未选择申请用户时设置为当前用户
        if (StringUtils.isEmpty(equipmentRepair.getApplyId())) {
            equipmentRepair.setApplyId(loginUser.getUsername());
        }
        //未选择申请时间时设置为当前时间
        if (equipmentRepair.getApplyTime() == null) {
            equipmentRepair.setApplyTime(new Date());
        }

        //todo
        //选择为设备时调整设备状态 为40（维保中）
        if ("eqp".equals(equipmentRepair.getTargetType())) {
            EquipmentEqpBasics eqpBasics = equipmentService.getById(EquipmentEqpBasics.class, equipmentRepair.getTargetId());
            //更新上一条记录的下一个操作时间
            equipmentEqpStatusRecordsService.saveRecordAndUpdatePreRecord(eqpBasics,40,"设备维修");
            //变更设备状态
            eqpBasics.setStatus(40);
            equipmentService.update(eqpBasics);

        }
        //区域时设置区域名称，编码
        /*if ("area".equals(equipmentRepair.getTargetType())) {
            EquipmentArea equipmentArea = equipmentAreaService.getById(EquipmentArea.class,equipmentRepair.getTargetId());
            String name = equipmentAreaService.getParentAllNameByPid(equipmentArea.getPid());
            equipmentRepair.setTargetName(name + " " + equipmentArea.getAreaName());
            equipmentRepair.setTargetCode(equipmentArea.getAreaCode());
        }*/
        //设置申请人工号
        User sysUser = userService.findByName(equipmentRepair.getApplyId());
        equipmentRepair.setApplyNo(sysUser.getUsername());
        if (equipmentRepair.getEmergencyFlag() != null && equipmentRepair.getEmergencyFlag() == 1) {
            equipmentRepair.setSourceType(SOURCE_JJ);
        } else {
            //设置为非紧急工单
            equipmentRepair.setEmergencyFlag(0);
            //设置工单来源 --- 默认为手动输入
            if (StringUtils.isEmpty(equipmentRepair.getSourceType())) {
                equipmentRepair.setSourceType(SOURCE_SG);
            }
        }

        //保存
        this.save(equipmentRepair);
        //添加操作历史
        insertOperate(equipmentRepair.getId(), "维修申请", "维修申请");
        //发送消息
        /*String faultTypeCode = equipmentRepair.getFaultTypeCode();
        if (StringUtils.isNotBlank(faultTypeCode)){
            FaultType faultType = faultTypeService.getById(FaultType.class, faultTypeCode);
            String groupId = faultType.getGroupId();
            EquipmentPersonGroup personGroup = JpaUtil.getOne(EquipmentPersonGroup.class,groupId);
            StringBuilder thirdUserIdsStr = new StringBuilder();
            if (personGroup!=null){
                List<String> userIds = equipmentPersonGroupDetailService.selectUserIdByGroupId(personGroup.getId());
                if (userIds.size()>0){
                    for (String userId:userIds){
                        User dbUser = JpaUtil.getOne(User.class, userId);
                        if (dbUser!=null&&StringUtils.isNotBlank(dbUser.getThirdId())){
                            thirdUserIdsStr.append(dbUser.getThirdId()).append(",");
                        }
                    }
                }
            }

            if (StringUtils.isNotBlank(thirdUserIdsStr)){
                String substring = thirdUserIdsStr.substring(0, thirdUserIdsStr.lastIndexOf(","));
                DingTalkMessagePojo dingTalkMessagePojo = new DingTalkMessagePojo();
                dingTalkMessagePojo.setMsgtype(DingTalkEnums.MsgType.LINK.getCode());
                LinkTypeContent linkTypeContent = new LinkTypeContent();
                linkTypeContent.setMessageUrl(executeDetailUrl+equipmentRepair.getOrderCode());
                linkTypeContent.setPicUrl("@lADOADmaWMzazQKA");
                String title = "维修申请处理";
                linkTypeContent.setTitle(title);
                linkTypeContent.setText("用户新增了维修申请，请及时处理，单号："+equipmentRepair.getOrderCode());
                dingTalkMessagePojo.setLink(linkTypeContent);
                //log.error("thirdUserIdsStr:"+substring+";"+JSONObject.toJSONString(dingTalkMessagePojo));
                messageService.sendMessage(channelCodes,"",substring.split(","),title, JSONObject.toJSONString(dingTalkMessagePojo));
            }
        }*/
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRepairById(EquipmentRepair equipmentRepair) {
        //设置申请人工号
        User sysUser = userService.findByName(equipmentRepair.getApplyId());
        equipmentRepair.setApplyNo(sysUser.getUsername());
        //区域时设置区域名称，编码
        if ("area".equals(equipmentRepair.getTargetType())) {
            EquipmentArea equipmentArea = equipmentAreaService.getById(EquipmentArea.class,equipmentRepair.getTargetId());
            //获取该区域的上级区域的名称
            String name = equipmentAreaService.getParentAllNameByPid(equipmentArea.getPid());
            equipmentRepair.setTargetName(name +"/"+ equipmentArea.getAreaName());
            equipmentRepair.setTargetCode(equipmentArea.getAreaCode());
        }
        //选择为设备时调整设备状态 为40（维保中）
        if ("eqp".equals(equipmentRepair.getTargetType())) {
            EquipmentEqpBasics eqpBasics = equipmentService.getById(EquipmentEqpBasics.class, equipmentRepair.getTargetId());
            //更新上一条记录的下一个操作时间
            equipmentEqpStatusRecordsService.saveRecordAndUpdatePreRecord(eqpBasics,40,"设备维修");
            //变更设备状态
            eqpBasics.setStatus(40);
            equipmentService.update(eqpBasics);
            equipmentRepair.setTargetCode(eqpBasics.getEqpCode());
            equipmentRepair.setTargetName(eqpBasics.getEqpName());

        }
        this.update(equipmentRepair);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendRepairById(EquipmentRepair tpmRepair) {
        EquipmentRepair bean = this.getById(EquipmentRepair.class,tpmRepair.getId());
        if (StringUtils.isEmpty(tpmRepair.getId()) || bean == null) {
            throw new MBootException("id为空或者未找到对应实体！");
        }
        if (bean.getOrderStatus().equals(CANCLE)){
            throw new MBootException(("单据已取消，不允许此操作！"));
        }
        bean.setDispatchMode("assign");
        //派工人员信息
        bean.setDistributePersonId(tpmRepair.getDistributePersonId());
        bean.setDistributeTime(new Date());

        //设置计划开始结束时间
        bean.setPlanRepairEndDate(tpmRepair.getPlanRepairEndDate());
        bean.setPlanRepairStartDate(tpmRepair.getPlanRepairStartDate());
        //改变状态---设置为派工状态
        bean.setOrderStatus(SEND);
        this.update(bean);
        //添加操作记录
        insertOperate(tpmRepair.getId(), "维修派工", "维修派工");

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void grabRepairById(EquipmentRepair tpmRepair) {
        EquipmentRepair bean = this.getById(EquipmentRepair.class,tpmRepair.getId());
        if (StringUtils.isEmpty(tpmRepair.getId()) || bean == null) {
            throw new MBootException("id为空或者未找到对应实体！");
        }
        if (bean.getOrderStatus().equals(CANCLE)){
            throw new MBootException(("单据已取消，不允许此操作！"));
        }
        bean.setDispatchMode("grab");
        User loginUser = SecurityUtils.getLoginUser();
        //执行人员信息
        bean.setDistributePersonId(loginUser.getUsername());
        bean.setDistributeTime(new Date());

        //设置计划开始结束时间
        bean.setPlanRepairEndDate(tpmRepair.getPlanRepairEndDate());
        bean.setPlanRepairStartDate(tpmRepair.getPlanRepairStartDate());
        //改变状态---设置为派工状态
        bean.setOrderStatus(SEND);
        this.update(bean);
        //添加操作记录
        insertOperate(tpmRepair.getId(), "维修抢单", "维修抢单");

    }


    /**
     * 添加操作记录
     *
     * @param repairId 维修ID
     * @param operate  操作
     * @param reason   原因（主要用具回退填写原因）
     */
    private void insertOperate(String repairId, String operate, String reason) {
        EquipmentRepairOperation operation = new EquipmentRepairOperation();
        //设置维修ID
        operation.setRepairId(repairId);
        //设置操作名称
        operation.setOperate(operate);
        //设置操作原因
        operation.setReason(reason);
        //设置操作时间
        operation.setOperateTime(new Date());
        //获取当前登录用户
        User loginUser = SecurityUtils.getLoginUser();
        //设置操作人
        operation.setOperator(loginUser.getNickname() + "/" + loginUser.getUsername());
        //保存
        repairOperationService.save(operation);
    }


    /**
     * 添加操作记录
     *
     * @param repairId 维修ID
     * @param operate  操作
     * @param reason   原因（主要用具回退填写原因）
     * @param time     时间戳
     */
    private void insertOperate(String repairId, String operate, String reason, long time) {
        EquipmentRepairOperation operation = new EquipmentRepairOperation();
        //设置维修ID
        operation.setRepairId(repairId);
        //设置操作名称
        operation.setOperate(operate);
        //设置操作原因
        operation.setReason(reason);
        //设置操作时间
        operation.setOperateTime(new Date(time));
        //获取当前登录用户
        User loginUser = SecurityUtils.getLoginUser();
        //设置操作人
        operation.setOperator(loginUser.getNickname() + "/" + loginUser.getUsername());
        //保存
        repairOperationService.save(operation);
    }

    /**
     * 改派
     *
     * @param reason
     * @param username
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reSendRepairById(String reason, String username, String id) {
        EquipmentRepair tpmRepair = this.getById(EquipmentRepair.class,id);
        if (StringUtils.isEmpty(id) || tpmRepair == null) {
            throw new MBootException("id为空或者未找到对应实体！");
        }

        if (tpmRepair.getOrderStatus().equals(CANCLE)){
            throw new MBootException(("单据已取消，不允许此操作！"));
        }
        //设置改派记录
        EquipmentRepairTransfer transfer = new EquipmentRepairTransfer();
        transfer.setRepairId(id);
        User user = userService.findByName(username);
        transfer.setNewExecutor(user.getNickname() + "/" + user.getUsername());
        //设置旧的人员信息
        if (tpmRepair.getDistributePersonId() != null) {
            User oldUser = userService.findByName(tpmRepair.getDistributePersonId());
            transfer.setOldExecutor(oldUser.getNickname() + "/" + oldUser.getUsername());
        }
        transfer.setReason(reason);
        transfer.setType("维修执行");
        repairTransferService.save(transfer);

        //设置新的改派人
        tpmRepair.setDistributePersonId(username);
        this.update(tpmRepair);
        //设置操作记录
        insertOperate(id, "维修改派", reason);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void start(EquipmentRepair equipmentRepair) {
        EquipmentRepair tpmRepair = this.getById(EquipmentRepair.class,equipmentRepair.getId());
        if (tpmRepair == null || tpmRepair.getOrderStatus() != SEND) {
            throw new MBootException("实体未找到或非未开始维修状态！");
        }
        if (tpmRepair.getOrderStatus().equals(CANCLE)){
            throw new MBootException(("单据已取消，不允许此操作！"));
        }
        tpmRepair.setOrderStatus(REPAIR);
        tpmRepair.setActualStartDate(new Date());
        tpmRepair.setPlanRepairStartDate(equipmentRepair.getPlanRepairStartDate());
        tpmRepair.setPlanRepairEndDate(equipmentRepair.getPlanRepairEndDate());
        this.update(tpmRepair);

        //设置操作记录
        insertOperate(equipmentRepair.getId(), "维修开始", "维修开始");
    }

    @Override
    @Transactional
    public Result<?> evaluate(EquipmentRepair equipmentRepair) {
        EquipmentRepair tpmRepair = this.getById(EquipmentRepair.class,equipmentRepair.getId());
        if (tpmRepair == null ) {
            return Result.error("未找到实体对象");
        }
        if (!tpmRepair.getOrderStatus().equals(FINISH) ){
            return Result.error("仅待验收状态可以评价！");
        }
        tpmRepair.setOrderStatus(CHECKED);
        tpmRepair.setEvaluateDate(new Date());
        tpmRepair.setEvaluateStar(equipmentRepair.getEvaluateStar());
        tpmRepair.setIsUsable(equipmentRepair.getIsUsable());
        tpmRepair.setEvaluateContent(equipmentRepair.getEvaluateContent());
        tpmRepair.setEvaluateUser(SecurityUtils.getLoginUser().getUsername());
        tpmRepair.setEvaluateImg(equipmentRepair.getEvaluateImg());
        this.update(tpmRepair);

        //设置操作记录
        insertOperate(equipmentRepair.getId(), "评分", "评分");
        return Result.OK(tpmRepair);
    }

    @Override
    @Transactional
    public Result<?> statement(EquipmentRepair equipmentRepair) {
        EquipmentRepair tpmRepair = this.getById(EquipmentRepair.class,equipmentRepair.getId());
        if (tpmRepair == null ) {
            return Result.error("未找到实体对象");
        }
        if (!tpmRepair.getOrderStatus().equals(REPAIR) ){
            return Result.error("仅维修中状态可以结单！");
        }
        tpmRepair.setOrderStatus(FINISH);
        tpmRepair.setMalfunctionReason(equipmentRepair.getMalfunctionReason());
        tpmRepair.setMalfunctionHandling(equipmentRepair.getMalfunctionHandling());
        tpmRepair.setMalfunctionImg(equipmentRepair.getMalfunctionImg());
        this.update(tpmRepair);

        insertOperate(equipmentRepair.getId(), "结单", "结单");

        //发送消息
        /*User dbUser = JpaUtil.getOne(User.class, equipmentRepair.getCreateBy());
        if (dbUser!=null&&StringUtils.isNotBlank(dbUser.getThirdId())){
            DingTalkMessagePojo dingTalkMessagePojo = new DingTalkMessagePojo();
            dingTalkMessagePojo.setMsgtype(DingTalkEnums.MsgType.LINK.getCode());
            LinkTypeContent linkTypeContent = new LinkTypeContent();
            linkTypeContent.setMessageUrl(applyDetailUrl+equipmentRepair.getOrderCode());
            linkTypeContent.setPicUrl("@lADOADmaWMzazQKA");
            String title = "维修评价";
            linkTypeContent.setTitle(title);
            linkTypeContent.setText("维修申请已处理完毕，请及时评价，单号："+equipmentRepair.getOrderCode());
            dingTalkMessagePojo.setLink(linkTypeContent);
            //log.error("thirdUserIdsStr:"+dbUser.getThirdId()+";"+JSONObject.toJSONString(dingTalkMessagePojo));
            messageService.sendMessage(channelCodes,"",dbUser.getThirdId().split(","),title, JSONObject.toJSONString(dingTalkMessagePojo));
        }*/
        return Result.OK(tpmRepair);
    }

    @Override
    @Transactional
    public Result<?> cancle(EquipmentRepair equipmentRepair) {
        EquipmentRepair tpmRepair = this.getById(EquipmentRepair.class,equipmentRepair.getId());
        if (tpmRepair == null ) {
            return Result.error("未找到实体对象");
        }
        if (!tpmRepair.getOrderStatus().equals(SEND)){
            return Result.error("仅待维修状态可以取消！");
        }
        tpmRepair.setOrderStatus(CANCLE);
        this.update(tpmRepair);

        insertOperate(equipmentRepair.getId(), "取消", "取消");
        return Result.OK(tpmRepair);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void finish(EquipmentRepair tpmRepair) {
        EquipmentRepair bean = this.getById(EquipmentRepair.class,tpmRepair.getId());
        if (bean == null || bean.getOrderStatus() != REPAIR) {
            throw new MBootException("实体未找到或未开始维修状态！");
        }
        if (tpmRepair.getOrderStatus().equals(CANCLE)){
            throw new MBootException(("单据已取消，不允许此操作！"));
        }
        //设置工单状态
        bean.setOrderStatus(FINISH);
        bean.setActualEndDate(new Date());
        bean.setOverFlag(0);
        //设置是逾期原因
        if (tpmRepair.getOverFlag() == 1) {
            bean.setOverFlag(1);
            bean.setOverdueReason(tpmRepair.getOverdueReason());
        }


        // 计算维修工时
        List<EquipmentRepairOperation> tpmRepairOperations = equipmentRepairOperationService.selectByMainId(bean.getId());
        if (!CollectionUtils.isEmpty(tpmRepairOperations)) {
            Date beginStop = new Date();
            long totalWorkTime = DateUtil.between(bean.getActualStartDate(), bean.getActualEndDate(), DateUnit.MINUTE);
            long totalStopTime = 0;
            // 循环计算暂停时长
            for (int i = 0; i < tpmRepairOperations.size(); i++) {
                if ("维修暂停".equals(tpmRepairOperations.get(i).getOperate())) {
                    beginStop = tpmRepairOperations.get(i).getOperateTime();
                }
                if ("维修暂停结束".equals(tpmRepairOperations.get(i).getOperate())) {
                    totalStopTime += DateUtil.between(beginStop,tpmRepairOperations.get(i).getOperateTime(), DateUnit.MINUTE);
                }
            }
            bean.setWorkMinutes(totalWorkTime - totalStopTime);
        }
        this.update(bean);
        //设置操作记录
        insertOperate(bean.getId(), "维修结束", "维修结束");
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void stopRepairById(String reason, String id) {
        EquipmentRepair tpmRepair = this.getById(EquipmentRepair.class,id);
        if (tpmRepair == null || tpmRepair.getOrderStatus() != REPAIR) {
            throw  new MBootException("实体未找到或未开始维修状态！");
        }
        if (tpmRepair.getOrderStatus().equals(CANCLE)){
            throw new MBootException(("单据已取消，不允许此操作！"));
        }
        tpmRepair.setOrderStatus(STOP);
        this.update(tpmRepair);

        //设置操作记录
        insertOperate(id, "维修暂停", reason);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void endStop(String id) {
        EquipmentRepair tpmRepair = this.getById(EquipmentRepair.class,id);
        if (tpmRepair == null || tpmRepair.getOrderStatus() != STOP) {
            throw  new MBootException("实体未找到或非暂停状态！");
        }
        if (tpmRepair.getOrderStatus().equals(CANCLE)){
            throw new MBootException(("单据已取消，不允许此操作！"));
        }
        tpmRepair.setOrderStatus(REPAIR);
        this.update(tpmRepair);

        //设置操作记录
        insertOperate(id, "维修暂停结束", "维修暂停结束");
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void check(String id,Integer evaluateStar, HttpServletRequest request) throws MBootException {
        EquipmentRepair tpmRepair = this.getById(EquipmentRepair.class,id);
        if (tpmRepair == null || tpmRepair.getOrderStatus() != FINISH) {
            throw  new MBootException("实体未找到或非维修完成状态！");
        }
        if (tpmRepair.getOrderStatus().equals(CANCLE)){
            throw new MBootException(("单据已取消，不允许此操作！"));
        }
        //获取当前登录用户
        User loginUser =  SecurityUtils.getLoginUser();
        tpmRepair.setOrderStatus(CHECKED);
        tpmRepair.setCheckTime(new Date());
        tpmRepair.setCheckUser(loginUser.getUsername());
        tpmRepair.setEvaluateStar(evaluateStar);
        this.update(tpmRepair);
        //若为设备时变更设备状态
        if ("eqp".equals(tpmRepair.getTargetType())) {
            EquipmentEqpBasics eqpBasics = equipmentService.getById(EquipmentEqpBasics.class,tpmRepair.getTargetId());
            //更新上一条记录的下一个操作时间
            equipmentEqpStatusRecordsService.saveRecordAndUpdatePreRecord(eqpBasics,30,"设备维修完成");
            eqpBasics.setStatus(30); //变更为使用中
            equipmentService.update(eqpBasics);
        }
        // 发起签核
//        activitiInstanceController.startOnlInstance(id, "5698109fffc24a468b1ee8e777e6d70f", request);
        //设置操作记录
        insertOperate(id, "维修验收", "维修验收");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reject(String id, String reason)throws MBootException  {
        EquipmentRepair tpmRepair = this.getById(EquipmentRepair.class,id);
        if (tpmRepair == null || tpmRepair.getOrderStatus() != REPAIR) {
            throw  new MBootException("实体未找到或非维修完成状态！");
        }
        if (tpmRepair.getOrderStatus().equals(CANCLE)){
            throw new MBootException(("单据已取消，不允许此操作！"));
        }
        tpmRepair.setOrderStatus(SEND);
        this.update(tpmRepair);

        //设置操作记录
        insertOperate(id, "验收回退", reason);
    }

    @Override
    public List<EquipmentRepair> queryRepairingList() {
        Integer[] status = {20,30,35};
        Criteria c = Criteria.create().addCriterion("orderStatus", Operator.IN, status);
        return list(EquipmentRepair.class,c);
    }

    @Override
    @Transactional
    public EquipmentRepair getByOrderCode(String orderCode) {
        return JpaUtil.linq(EquipmentRepair.class).collect("orderCode",EquipmentRepairUrgeLine.class,"orderCode").equal("orderCode", orderCode).findOne();
    }

    @Override
    @Transactional
    public void signOffBack(String repairId,String reason){
        EquipmentRepair tpmRepair = this.getById(EquipmentRepair.class,repairId);
        if (tpmRepair == null || tpmRepair.getOrderStatus() != CHECKED) {
            throw  new MBootException("实体未找到或非维修完成状态！");
        }
        tpmRepair.setOrderStatus(SEND);
        this.update(tpmRepair);

        //设置操作记录
        insertOperate(repairId, "签核回退", reason);

        //选择为设备时调整设备状态 为40（维保中）
        if ("eqp".equals(tpmRepair.getTargetType())) {
            EquipmentEqpBasics eqpBasics = equipmentService.getById(EquipmentEqpBasics.class,tpmRepair.getTargetId());
            //更新上一条记录的下一个操作时间
            equipmentEqpStatusRecordsService.saveRecordAndUpdatePreRecord(eqpBasics,40,"设备维修");
            //变更设备状态
            eqpBasics.setStatus(40);
            equipmentService.update(eqpBasics);

        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void executeOffLineData(EquipmentRepair tpmRepair, List<Map> history) {
        EquipmentRepair bean = this.getById(EquipmentRepair.class,tpmRepair.getId());
        if (bean==null){
            throw new MBootException("对象不存在！");
        }
//        tpmRepairMapper.updateById(tpmRepair);
        //查找该维修执行的记录
        List<Map> repairId = history.stream().filter(map -> tpmRepair.getId().equals(map.get("repairId"))).collect(Collectors.toList());
        //保存维修记录
        repairId.stream().forEach(m -> {
            String operate = "维修开始";
            String reason = "维修开始";
            if ("start".equals(m.get("state"))) {
                operate = "维修开始";
                reason = "维修开始";
            } else if ("stop".equals(m.get("state"))) {
                operate = "维修暂停";
                reason = m.get("reason") + "";
            } else if ("resStart".equals(m.get("state"))) {
                operate = "维修暂停结束";
                reason = "维修暂停结束";
            } else if ("finish".equals(m.get("state"))) {
                operate = "维修结束";
                reason = "维修结束";

                // 计算维修工时
                List<EquipmentRepairOperation> tpmRepairOperations = equipmentRepairOperationService.selectByMainId(bean.getId());
                if (!CollectionUtils.isEmpty(tpmRepairOperations)) {
                    Date beginStop = new Date();
                    long totalWorkTime = DateUtil.between(bean.getActualStartDate()==null?tpmRepair.getActualStartDate():bean.getActualStartDate(), tpmRepair.getActualEndDate(), DateUnit.MINUTE);
                    long totalStopTime = 0;
                    // 循环计算暂停时长
                    for (int i = 0; i < tpmRepairOperations.size(); i++) {
                        if ("维修暂停".equals(tpmRepairOperations.get(i).getOperate())) {
                            beginStop = tpmRepairOperations.get(i).getOperateTime();
                        }
                        if ("维修暂停结束".equals(tpmRepairOperations.get(i).getOperate())) {
                            totalStopTime += DateUtil.between(beginStop,tpmRepairOperations.get(i).getOperateTime(), DateUnit.MINUTE);
                        }
                    }
                    tpmRepair.setWorkMinutes(totalWorkTime - totalStopTime);
                }
            }
            //添加操作记录
            insertOperate(tpmRepair.getId(), operate, reason, (long) m.get("time"));
        });
        this.update(tpmRepair);
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<EquipmentRepair>> getNowadaysListByAreaid(String areaid) {
        String treeChildIds = equipmentAreaService.queryTreeChildIds(areaid);//获取所有子孙节点
        if (StringUtils.isBlank(treeChildIds)){
            return Result.error("入参未能匹配到对应区域数据");
        }
        String today = DateUtil.format(new Date(), "yyyy-MM-dd");
        Criteria dateCriteria = Criteria.create();
        dateCriteria.addCriterion("createTime",Operator.GE,today);
        //查询所有目标类别为区域的维修单
        List<EquipmentRepair> areaList = JpaUtil.linq(EquipmentRepair.class)
                .equal("targetType", "area")
                .in("targetId", Arrays.asList(treeChildIds.split(",")))
                .where(dateCriteria)
                .list();
        //查询当天所有的
        List<EquipmentRepair> eqpList = JpaUtil.linq(EquipmentRepair.class)
                .equal("targetType", "eqp")
                .exists(EquipmentEqpBasics.class)
                    .equalProperty("id", "targetId")
                    .in("areaId", Arrays.asList(treeChildIds.split(",")))
                .end()
                .where(dateCriteria)
                .list();
        //合并集合
        areaList.addAll(eqpList);
        return Result.OK(areaList);
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<Map<String, Object>>> getSevendaysCntGroupbyFaultType(String areaid) {
        String treeChildIds = equipmentAreaService.queryTreeChildIds(areaid);//获取所有子孙节点
        if (StringUtils.isBlank(treeChildIds)){
            return Result.error("入参未能匹配到对应区域数据");
        }
        String lastWeek = DateUtil.format(DateUtil.lastWeek(), "yyyy-MM-dd");
        Criteria dateCriteria = Criteria.create();
        dateCriteria.addCriterion("createTime",Operator.GE,lastWeek);
        //查询所有目标类别为区域的维修单
        List<EquipmentRepair> areaList = JpaUtil.linq(EquipmentRepair.class)
                .collect("typeCode",FaultType.class,"faultTypeCode")
                .equal("targetType", "area")
                .in("targetId", Arrays.asList(treeChildIds.split(",")))
                .where(dateCriteria)
                .list();
        //查询七天所有的
        List<EquipmentRepair> eqpList = JpaUtil.linq(EquipmentRepair.class)
                .collect("typeCode",FaultType.class,"faultTypeCode")
                .equal("targetType", "eqp")
                .exists(EquipmentEqpBasics.class)
                .equalProperty("id", "targetId")
                .in("areaId", Arrays.asList(treeChildIds.split(",")))
                .end()
                .where(dateCriteria)
                .list();
        //合并集合
        areaList.addAll(eqpList);
        List<Map<String, Object>> returnList = new ArrayList<>();
        if (areaList.size()>0){
            Map<String, List<EquipmentRepair>> collect = areaList.stream().collect(Collectors.groupingBy(EquipmentRepair::getFaultTypeCode));
            for (String key: collect.keySet()){
                if (StringUtils.isNotBlank(key)){
                    List<EquipmentRepair> equipmentRepairs = collect.get(key);
                    EquipmentRepair equipmentRepair = equipmentRepairs.get(0);
                    Map<String, Object> returnMap = new HashMap<>();
                    FaultType faultType = equipmentRepair.getFaultType();
                    if (faultType!=null){
                        returnMap.put("typeCode",faultType.getTypeCode());
                        returnMap.put("typeName",faultType.getTypeName());
                    }else{
                        returnMap.put("typeCode",key);
                        returnMap.put("typeName",key);
                    }
                    returnMap.put("cnt",equipmentRepairs.size());
                    returnList.add(returnMap);
                }
            }
        }
        return Result.OK(returnList);
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<Map<String, Object>>> getSevendaysCntGroupbySecondArea(String areaid) {
        EquipmentArea byId = equipmentAreaService.getById(EquipmentArea.class, areaid);
        if (!byId.getPid().equals("0")){
            return Result.error("入参areaid并非一级区域节点，无法正常统计！");
        }
        String lastWeek = DateUtil.format(DateUtil.lastWeek(), "yyyy-MM-dd");
        Criteria dateCriteria = Criteria.create();
        dateCriteria.addCriterion("createTime",Operator.GE,lastWeek);
        List<Map<String, Object>> returnList = new ArrayList<>();
        //拿到所有的二级区域节点
        List<EquipmentArea> secondaryAreaList = JpaUtil.linq(EquipmentArea.class).equal("pid", areaid).list();
        if (secondaryAreaList.size()>0){
            for (EquipmentArea area:secondaryAreaList){
                String secondaryId = area.getId();
                String treeChildIds = equipmentAreaService.queryTreeChildIds(secondaryId);//获取二级下所有子孙节点(包括二级)
                if (StringUtils.isBlank(treeChildIds)){
                    return Result.error("区域ID【"+secondaryId+"】未能匹配到对应区域数据");
                }
                //查询所有目标类别为区域的维修单
                List<EquipmentRepair> areaList = JpaUtil.linq(EquipmentRepair.class)
                        .equal("targetType", "area")
                        .in("targetId", Arrays.asList(treeChildIds.split(",")))
                        .where(dateCriteria)
                        .list();
                //查询七天所有的
                List<EquipmentRepair> eqpList = JpaUtil.linq(EquipmentRepair.class)
                        .equal("targetType", "eqp")
                        .exists(EquipmentEqpBasics.class)
                        .equalProperty("id", "targetId")
                        .in("areaId", Arrays.asList(treeChildIds.split(",")))
                        .end()
                        .where(dateCriteria)
                        .list();
                //合并
                areaList.addAll(eqpList);
                Map<String, Object> returnMap = new HashMap<>();
                returnMap.put("areaCode",area.getAreaCode());
                returnMap.put("areaName",area.getAreaName());
                returnMap.put("cnt",areaList.size());
                returnList.add(returnMap);
            }
        }
        return Result.OK(returnList);
    }

    /*   public static void main(String[] args) {
        String lastWeek = DateUtil.format(DateUtil.lastWeek(), "yyyy-MM-dd");
        String today = DateUtil.format(new Date(), "yyyy-MM-dd");
        System.out.println(lastWeek);
        System.out.println(today);
    }*/
}
